package xcmg.device.service.warehouse;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xcmg.device.dao.entity.PriMaterialsDO;
import xcmg.device.dao.entity.warehouse.DeliveryInstructionDO;
import xcmg.device.dao.entity.warehouse.DeliveryInstructionDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDetailDO;
import xcmg.device.dao.mapper.PriMaterialsMapper;
import xcmg.device.dao.mapper.warehouse.DeliveryInstructionDetailMapper;
import xcmg.device.dao.mapper.warehouse.DeliveryInstructionMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundMapper;
import xcmg.device.infra.ErrorCode;
import xcmg.device.service.vo.warehouse.DeliveryInstructionDetailVO;
import xcmg.device.service.vo.warehouse.DeliveryInstructionVO;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.log.LogHelper;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.StringUtil;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class DeliveryInstructionDetailService {

    @Autowired
    private DeliveryInstructionDetailMapper deliveryInstructionDetailMapper;

    @Autowired
    private DeliveryInstructionMapper deliveryInstructionMapper;

    @Autowired
    private PriMaterialsMapper priMaterialsMapper;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private CommonService commonService;

    @Autowired
    private WarehouseInboundMapper warehouseInboundMapper;

    @Autowired
    private WarehouseInboundDetailMapper warehouseInboundDetailMapper;

    /**
     * @Author: WangKe
     * @Description: 新增配送指令入库详情记录
     * @Date: 2018/4/17 0017
     */
    @Transactional(rollbackFor = Exception.class)
    public List<DeliveryInstructionDetailDO> add(DeliveryInstructionDO deliveryInstructionDO, List<Map<String, String>> dataList, String userId, String orgId)throws Exception{
        boolean success;
        DeliveryInstructionDetailDO detailDO;
        DeliveryInstructionDetailDO temp;
        List<DeliveryInstructionDetailDO> detailDOList = new ArrayList<>();
        for(Map<String, String> detailMap : dataList){
            String materialNo = detailMap.get("MATNR").replaceAll("^(0+)", "");
            Integer rowNo = new BigDecimal(detailMap.get("ZPSZLHZPOS")).setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
            temp = deliveryInstructionDetailMapper.findByDeliveryOrderAndMaterialNo(deliveryInstructionDO.getDeliveryOrder(), materialNo, rowNo, orgId);
            if(temp != null){
                success = this.update(temp, detailMap);
                if(!success){
                    throw new Exception("更新配送指令入库状态失败");
                }
                continue;
            }
            ActionResult<String> textResult = fastGenClient.textGuid();
            if (textResult.getCode() != ErrorCode.Success.getCode())
            {
                throw new Exception("生成详情记录失败");
            }
            detailDO = new DeliveryInstructionDetailDO();
            detailDO.setDeliveryOrder(deliveryInstructionDO.getDeliveryOrder());
            detailDO.setDeliveryInstructionNo(deliveryInstructionDO.getDeliveryInstructionNo());
            detailDO.setRowNo(new BigDecimal(detailMap.get("ZPSZLHZPOS")).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
            BigDecimal totalAmount=new BigDecimal(detailMap.get("ZPSSL")).setScale(3, BigDecimal.ROUND_HALF_UP);
            BigDecimal finishedAmount=new BigDecimal(detailMap.get("ZYPSSL")==null?"0":detailMap.get("ZYPSSL")).setScale(3, BigDecimal.ROUND_HALF_UP);//已配送数量
            detailDO.setAmount(totalAmount.subtract(finishedAmount).add(detailDO.getRealAmount()==null?new BigDecimal(0):detailDO.getRealAmount()));
            //detailDO.setAmount(new BigDecimal(detailMap.get("ZPSSL")).setScale(3, BigDecimal.ROUND_HALF_UP));
            detailDO.setInnerAmount(new BigDecimal(detailMap.get("ZYPSSL_GI")).setScale(3, BigDecimal.ROUND_HALF_UP));
            detailDO.setOuterAmount(new BigDecimal(detailMap.get("ZYPSSL_GR")).setScale(3, BigDecimal.ROUND_HALF_UP));
            detailDO.setRealAmount(BigDecimal.ZERO);
            detailDO.setPostingState(0);
            detailDO.setCreateId(userId);
            detailDO.setOrgId(orgId);

            //判断基础表里是否有此零件，如果没有就新增
            PriMaterialsDO priMaterialsDO = priMaterialsMapper.itemByNo(materialNo, orgId);
            if(priMaterialsDO == null){
                throw new Exception("基础零件中没有此零件，"+materialNo+"，"+detailMap.get("MAKTX"));
//                PriMaterialsDO newPriMaterialsDO  = priMaterialsMapper.itemByNo(detailMap.get("MATNR"), deliveryInstructionDO.getSupplierOrgId());
//                if(newPriMaterialsDO == null){
//                    throw new Exception("供应商基础零件中未找到此零件，"+detailMap.get("MAKTX"));
//                }
//                priMaterialsDO = new PriMaterialsDO();
//                BeanUtils.copyProperties(newPriMaterialsDO, priMaterialsDO);
//                priMaterialsDO.setOrgId(orgId);
//                success = priMaterialsMapper.insert(priMaterialsDO)>0;
//                if(!success){
//                    throw new Exception("向基础零件中新增此零件失败，"+detailMap.get("MAKTX"));
//                }
            }
            detailDO.setMaterialNo(priMaterialsDO.getMaterialsNo());
            detailDO.setMaterialName(priMaterialsDO.getMaterialsDes());
            detailDO.setMaterialType(priMaterialsDO.getMaterialsType());
            detailDO.setUnit(priMaterialsDO.getUnit());

            detailDO.setId(textResult.getValue());
            detailDO.setState(0);
            detailDO.setCreateDate(new Date());
            detailDO.setCreateName(commonService.getUserName(userId));
            detailDO.setRealAmount(BigDecimal.ZERO);
            detailDOList.add(detailDO);

            success = deliveryInstructionDetailMapper.insert(detailDO)>0;
            if(!success){
                throw new Exception("新增配送指令入库详情记录失败");
            }
        }
        int total = deliveryInstructionDetailMapper.findNum(deliveryInstructionDO.getDeliveryOrder(), deliveryInstructionDO.getOrgId());
        int none = deliveryInstructionDetailMapper.findNumByState(deliveryInstructionDO.getDeliveryOrder(), 0, deliveryInstructionDO.getOrgId());
        int all = deliveryInstructionDetailMapper.findNumByState(deliveryInstructionDO.getDeliveryOrder(), 2, deliveryInstructionDO.getOrgId());
        if(none == total){
            deliveryInstructionDO.setState(0);
        }else if(all == total){
            deliveryInstructionDO.setState(2);
        }else{
            deliveryInstructionDO.setState(1);
        }
        success = deliveryInstructionMapper.updateByPrimaryKeySelective(deliveryInstructionDO)>0;
        if(!success){
            throw new Exception("更新配送指令入库状态失败");
        }
        return detailDOList;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean update(DeliveryInstructionDetailDO detailDO, Map<String, String> detailMap)throws Exception{
        detailDO.setRowNo(new BigDecimal(detailMap.get("ZPSZLHZPOS")).setScale(0, BigDecimal.ROUND_HALF_UP).intValue());
        //BigDecimal totalAmount=new BigDecimal(detailMap.get("ZPSSL")).setScale(3, BigDecimal.ROUND_HALF_UP);
        //BigDecimal finishedAmount=new BigDecimal(detailMap.get("ZYPSSL")==null?"0":detailMap.get("ZYPSSL")).setScale(3, BigDecimal.ROUND_HALF_UP);//已配送数量
        //detailDO.setAmount(totalAmount.subtract(finishedAmount).add(detailDO.getRealAmount()==null?new BigDecimal(0):detailDO.getRealAmount()));
        detailDO.setInnerAmount(new BigDecimal(detailMap.get("ZYPSSL_GI")).setScale(3, BigDecimal.ROUND_HALF_UP));
        detailDO.setOuterAmount(new BigDecimal(detailMap.get("ZYPSSL_GR")).setScale(3, BigDecimal.ROUND_HALF_UP));
        if(detailDO.getAmount().compareTo(detailDO.getRealAmount()) < 0){
            LogHelper.error("配送数量不能小于实际入库数量，配送指令："+detailDO.getDeliveryInstructionNo()+"，零件："+detailMap.get("MAKTX")+"，配送数量："+detailDO.getAmount(), ErrorCode.RequestIdError.getCode());
            throw new Exception("配送数量不能小于实际入库数量，配送指令："+detailDO.getDeliveryInstructionNo()+"，零件："+detailMap.get("MAKTX")+"，配送数量："+detailDO.getAmount());
        }
        if(detailDO.getRealAmount().compareTo(BigDecimal.ZERO) == 0){
            detailDO.setState(0);
        }else{
            if(detailDO.getAmount().compareTo(detailDO.getRealAmount()) > 0){
                detailDO.setState(1);
            }else{
                detailDO.setState(2);
            }
        }

        boolean successs = deliveryInstructionDetailMapper.updateByPrimaryKeySelective(detailDO)>0;
        if(!successs){
            throw new Exception("更新配送指令详情失败");
        }

        WarehouseInboundDetailDO inboundDetailDO = warehouseInboundDetailMapper.findByBusinessOrderAndRowNo(detailDO.getDeliveryOrder(), detailDO.getRowNo(), detailDO.getOrgId());
        if(inboundDetailDO == null){
            throw new Exception("更新配送指令详情失败");
        }
        inboundDetailDO.setAmount(detailDO.getAmount());
        inboundDetailDO.setStatus(detailDO.getState());
        if(inboundDetailDO.getPrintNum().compareTo(inboundDetailDO.getAmount()) > 0){
            throw new Exception("配送数量不能小于已打印数量，配送数量："+detailDO.getAmount()+"，已打印数量："+inboundDetailDO.getPrintNum());
        }
        if(inboundDetailDO.getPrintNum().equals(inboundDetailDO.getAmount())){
            inboundDetailDO.setPrintState(2);
        }else{
            inboundDetailDO.setPrintState(1);
        }
        successs = warehouseInboundDetailMapper.updateByPrimaryKeySelective(inboundDetailDO)>0;
        if(!successs){
            throw new Exception("更新配送指令详情失败");
        }
        return true;
    }

    private String getMaterialNo(String materialNo){
        if(StringUtil.isNullOrEmpty(materialNo)){
            return "";
        }
        BigDecimal m = new BigDecimal(materialNo);
        return m.intValue()+"";
    }

    /**
     * @Author: WangKe
     * @Description: 只新增入库单详情记录
     * @Date: 2018/4/17 0017
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addInboundDetail(List<DeliveryInstructionDetailDO> detailDOList, String orgId)throws Exception{
        if(ListUtil.isNullOrEmpty(detailDOList)){
            return true;
        }
        WarehouseInboundDO inboundDO = warehouseInboundMapper.selectByOrder(detailDOList.get(0).getDeliveryOrder(), orgId);
        DeliveryInstructionDO instructionDO = deliveryInstructionMapper.selectByDeliveryOrder(detailDOList.get(0).getDeliveryOrder(), orgId);
        if(inboundDO == null || instructionDO == null){
            return false;
        }
        WarehouseInboundDetailDO inboundDetailDO;
        boolean success;
        for(DeliveryInstructionDetailDO detailDO : detailDOList){
            ActionResult<String> textResult = fastGenClient.textGuid();
            if (textResult.getCode() != ErrorCode.Success.getCode()) {
                throw new Exception("生成详情记录失败");
            }
            inboundDetailDO = new WarehouseInboundDetailDO();
            BeanUtils.copyProperties(detailDO, inboundDetailDO);
            inboundDetailDO.setInboundOrder(inboundDO.getInboundOrder());
            inboundDetailDO.setBusinessSingle(detailDO.getDeliveryOrder().substring(0, 4));
            inboundDetailDO.setBusinessOrder(detailDO.getDeliveryOrder());
            inboundDetailDO.setCreaterName(detailDO.getCreateName());
            inboundDetailDO.setStatus(0);
            inboundDetailDO.setPrintNum(BigDecimal.ZERO);
            inboundDetailDO.setPrintState(0);

            success = warehouseInboundDetailMapper.insert(inboundDetailDO)>0;
            if(!success){
                throw new Exception("生成详情记录失败");
            }
        }
        if(inboundDO.getStatus() == 2){
            inboundDO.setStatus(1);
            success = warehouseInboundMapper.updateByPrimaryKeySelective(inboundDO)>0;
            if(!success){
                throw new Exception("更新入库事务单主表状态失败");
            }
            instructionDO.setState(1);
            deliveryInstructionMapper.updateByPrimaryKeySelective(instructionDO);
            if(!success){
                throw new Exception("更新配送指令入库单主表状态失败");
            }
        }
        return true;
    }

    /**
     * @Author: WangKe
     * @Description: 根据配送指令入库单号查询详情记录
     * @Date: 2018/4/17 0017
     */
    public List<DeliveryInstructionDetailDO> findByDeliveryOrder(String abnormalNo, String orgId){
        if(abnormalNo == null){
            return new ArrayList<>();
        }
        List<DeliveryInstructionDetailDO> list =  deliveryInstructionDetailMapper.findByDeliveryOrderForLocationUser(abnormalNo, orgId);
        if(CollectionUtils.isNotEmpty(list)){
            for(DeliveryInstructionDetailDO model : list){
                if(model.getRealAmount() == null){
                    model.setRealAmount(BigDecimal.ZERO);
                }
            }
        }
        return list;
    }

    /**
     * @Author: WangKe
     * @Description: 根据入库单号删除入库详情记录
     * @Date: 2018/4/17 0017
     */
    public ErrorCode deleteByDeliveryOrder(String abnormalNo, String orgId){
        return deliveryInstructionDetailMapper.deleteByDeliveryOrder(abnormalNo, orgId)>0? ErrorCode.Success: ErrorCode.WarehouseIdError;
    }

    /**
     * @Author: WangKe
     * @Description: 根据入库单号删除入库详情记录
     * @Date: 2018/1/26 0026
     */
    public ErrorCode deleteByDeliveryOrderList(List<String> orderList, String orgId){
        return deliveryInstructionDetailMapper.removeByOrderList(orderList, orgId)>0? ErrorCode.Success: ErrorCode.WarehouseIdError;
    }

    /**
     * @Author: WangKe
     * @Description: 新增入库记录时，更新配送指令入库单和详情的状态
     * @Date: 2018/2/6 0006
     */
    public boolean updateByInbound(String abnormalNo, String materialNo, BigDecimal realAmount,
                                   Integer singelState, Integer totalState, Integer rowNo, String orgId)throws Exception{
        DeliveryInstructionDetailVO detailVO = new DeliveryInstructionDetailVO();
        detailVO.setDeliveryOrder(abnormalNo);
        detailVO.setMaterialNo(materialNo);
        detailVO.setOrgId(orgId);
        detailVO.setRowNo(rowNo);
        List<DeliveryInstructionDetailDO> list = deliveryInstructionDetailMapper.list(detailVO);
        if(ListUtil.isNullOrEmpty(list)){
            return false;
        }
        DeliveryInstructionDetailDO detailDO = list.get(0);
        if(realAmount.compareTo(detailDO.getAmount()) > 0){
            throw new Exception("实际入库数量不能大于计划入库数量");
        }
        detailDO.setRealAmount(realAmount);
        detailDO.setState(singelState);
        boolean success = deliveryInstructionDetailMapper.updateByPrimaryKeySelective(detailDO)>0;
        if(success){
            DeliveryInstructionVO inboundVO = new DeliveryInstructionVO();
            inboundVO.setDeliveryOrder(abnormalNo);
            inboundVO.setOrgId(orgId);
            List<DeliveryInstructionDO> inboundList = deliveryInstructionMapper.list(inboundVO);
            if(ListUtil.isNullOrEmpty(inboundList)){
                return false;
            }
            DeliveryInstructionDO inboundDO = inboundList.get(0);
            inboundDO.setState(totalState);
            success = deliveryInstructionMapper.updateByPrimaryKeySelective(inboundDO)>0;
        }
        return success;
    }

    /**
     * 1.errorMsg为空，如果当前未过账，则未同步，如果当前部分过账或者已经过账，说明同步成功
     * 2.errorMsg不为空，则前一步操作有错，说明同步失败
     *
     * @param postingState
     * @param errorMsg
     * @return
     */
    public int getSapSynStatus(Integer postingState, String errorMsg) {
        if (StringUtils.isBlank(errorMsg)) {
            return DeliveryInstructionDetailVO.POSTING_STATUS_NO.equals(postingState) ?
                    DeliveryInstructionDetailVO.SAP_SYN_NO : DeliveryInstructionDetailVO.SAP_SYN_SUCCESS;
        }
        return DeliveryInstructionDetailVO.SAP_SYN_FAILURE;
    }
}
